package cheme.Interpreter.AST.Type;

import cheme.Interpreter.AST.Interfaces.IAstString;
import cheme.Interpreter.AST.Interfaces.IAstType;
import cheme.Interpreter.AST.Interfaces.IObserver;
import cheme.Interpreter.AST.Interfaces.ISubject;
import cheme.Interpreter.AST.Interfaces.SubjectCore;

public class AstType implements IAstType, Cloneable
{
	IAstString unit = null;
	IAstString material = null;
	
	private SubjectCore subjectCore = new SubjectCore(this);

	public AstType()
	{
	}
	
	public AstType(IAstString unit, IAstString material)
	{
		super();
		this.unit = unit;
		this.material = material;
	}
	
	@Override
	public IAstType clone()
	{
		return new AstType(
				(IAstString)getUnit().clone(), 
				(IAstString)getMaterial().clone());
	}

	/**
	 * @return the material
	 */
	protected IAstString getMaterial()
	{
		return material;
	}

	/**
	 * @param material the material to set
	 */
	protected void setMaterial(IAstString material)
	{
		this.material = material;
	}

	/**
	 * @return the unit
	 */
	protected IAstString getUnit()
	{
		return unit;
	}

	/**
	 * @param unit the unit to set
	 */
	protected void setUnit(IAstString unit)
	{
		this.unit = unit;
	}
	
	@Override
	public String toString()
	{
		if(null != getUnit() && null != getMaterial())
		{
			return getUnit().toString() + " " + getMaterial().toString();
		}
		else
		{
			return 
			((null != getUnit()) ? getUnit().toString() : "") + 
			((null != getMaterial()) ? getMaterial().toString() : "");
		}
	}
	

	public boolean equals(IAstType type)
	{
		return toString().equals(type.toString()); 
	}

	public double evaluate()
	{
		return 1.0;
	}
	
	public boolean isUnknown()
	{
		return false;
	}
		
	public ValueationState getValueationState()
	{
		return ValueationState.Evaluated;
	}
	
	public IAstType getType()
	{
		return this;
	}
	
	public void notify(ISubject s)
	{
		notifyObservers();
	}
	
	public void attach(IObserver o)
	{
		subjectCore.attach(o);
	}

	public void detach(IObserver o)
	{
		subjectCore.detach(o);
	}

	public void notifyObservers()
	{
		subjectCore.notifyObservers();
	}
}
